﻿using Report_Dal.TiJian;
using Report_Dal.Web;
using Report_IDal.TiJian;
using Report_IDal.Web;
using Report_IService.Web;
using Report_Model.Basic;
using Report_Model.Db;
using Report_Model.Web;
using Report_Unity.Basic;
using Report_Unity.Unitys;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Report_Service.Web
{
    public class ReportService : IReportService
    {
        private IT_EmployeeDal T_EmployeeDal = new T_EmployeeDal(ConfigSource.tab_web);
        private IS_Report_ItemConfigDal S_Report_ItemConfigDal = new S_Report_ItemConfigDal(ConfigSource.tab_web);
        private IT_CompanyDal T_CompanyDal = new T_CompanyDal(ConfigSource.tab_web);
        private IT_UserDal T_UserDal = new T_UserDal(ConfigSource.tab_web);
        private IT_QueryReport_RecordDal T_QueryReport_RecordDal = new T_QueryReport_RecordDal(ConfigSource.tab_web);

        private ITJ_TiJianBDal TJ_TiJianBDal = new TJ_TiJianBDal(ConfigSource.tab_tj);
        private ITJ_BAOGAODal TJ_BAOGAODal = new TJ_BAOGAODal(ConfigSource.tab_tj);
        private ITJ_ImagesDal TJ_ImagesDal = new TJ_ImagesDal(ConfigSource.tab_tj);

        private ITJ_PDF_BGDal TJ_PDF_BGDal = null;

        public ReportService(string conn)
        {
            TJ_PDF_BGDal = new TJ_PDF_BGDal(conn);
        }

        #region 团体查报告
        /// <summary>
        /// 获取单位信息
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="hid"></param>
        /// <returns></returns>
        public ResultInfo GetReportCompany(string userid, string hid)
        {
            if (string.IsNullOrEmpty(hid))
                return CodeStatus.error_201.GetStatus($"{nameof(hid)}必传");
            if (string.IsNullOrEmpty(userid))
                return CodeStatus.error_201.GetStatus($"{nameof(userid)}必传");

            T_User user = T_UserDal.GetAsNoTracking(a => a.user_id == userid && a.hospital_id == hid).FirstOrDefault();
            if (user == null)
                return CodeStatus.error_202.GetStatus("无用户");

            // 需要身份证号、手机号和姓名都匹配上
            T_Employee employee = T_EmployeeDal.GetAsNoTracking(a => a.hospital_id == hid && a.idcard == user.user_idcard && a.phone == user.user_phone && a.name == user.user_name).FirstOrDefault();
            if (employee == null)
                return CodeStatus.error_202.GetStatus("无该员工信息");

            var company = T_CompanyDal.GetAsNoTracking(a => a.hospital_id == hid && a.company_id == employee.company_id)
                .Select(a => new { company_name = a.company_name, company_desc = a.company_desc })
                .FirstOrDefault();

            object objResult = new
            {
                userid = userid,
                hid = hid,
                cid = employee.company_id,
                company_name = company.company_name,
                company_desc = company.company_desc
            };

            ResultInfo res = CodeStatus.success.GetStatus();
            res.data = objResult;
            return res;
        }

        public ResultInfo GetListEmployee(string hid, string cid, string userid)
        {
            if (string.IsNullOrEmpty(hid))
                return CodeStatus.error_201.GetStatus($"{nameof(hid)}必传");
            if (string.IsNullOrEmpty(cid))
                return CodeStatus.error_201.GetStatus($"{nameof(cid)}必传");
            if (string.IsNullOrEmpty(userid))
                return CodeStatus.error_201.GetStatus($"{nameof(userid)}必传");

            List<T_Employee> listEmployee = T_EmployeeDal.GetAsNoTracking(a => a.hospital_id == hid && a.company_id == cid).OrderBy(a => a.sort).ThenBy(a => a.id).ToList();

            List<object> list = new List<object>();
            foreach (T_Employee employee in listEmployee)
            {
                string name = employee.name;
                string idcard = employee.idcard;
                string phone = employee.phone;

                ReportEmployeeTicket reportEmployeeTicket = new ReportEmployeeTicket();
                reportEmployeeTicket.hid = hid;
                reportEmployeeTicket.idcard = idcard;
                reportEmployeeTicket.phone = phone;
                reportEmployeeTicket.name = name;
                reportEmployeeTicket.gid = Guid.NewGuid();
                reportEmployeeTicket.userid = userid;
                string jsonTicket = JsonXmlUtils.SerializeObject(reportEmployeeTicket);
                string ticket = DesUtils.Encrypt(jsonTicket);
                object obj = new { name = name, idcard = StringUtils.ReplaceWithSpecialChar(idcard), phone = StringUtils.ReplaceWithSpecialChar(phone), ticket = ticket };

                list.Add(obj);
            }

            ResultInfo res = CodeStatus.success.GetStatus();
            res.data = new { list = list };
            return res;
        }

        public ResultInfo GetListGroupReport(string ticket)
        {
            if (string.IsNullOrEmpty(ticket))
                return CodeStatus.error_201.GetStatus($"{nameof(ticket)}必传");

            ReportEmployeeTicket reportEmployeeTicket;
            try
            {
                reportEmployeeTicket = JsonXmlUtils.DeserializeObject<ReportEmployeeTicket>(ticket);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return CodeStatus.error_210.GetStatus();
            }

            ResultInfo res = GetListReport(reportEmployeeTicket.idcard, reportEmployeeTicket.phone, reportEmployeeTicket.hid);

            // 团体查询
            bool b = InsQueryReportRecord(reportEmployeeTicket.userid, reportEmployeeTicket.idcard, reportEmployeeTicket.name, reportEmployeeTicket.phone, reportEmployeeTicket.hid, SearchReportTypeEnum.group.GetEnumDesc());
            if (!b)
                return CodeStatus.error_301.GetStatus("查询记录插入失败");

            return res;
        }
        #endregion

        /// <summary>
        /// 查询本人报告
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="hid"></param>
        /// <returns></returns>
        public ResultInfo GetListReport(string userid,string hid)
        {
            if (string.IsNullOrEmpty(userid))
                return CodeStatus.error_201.GetStatus($"{nameof(userid)}必传");
            if (string.IsNullOrEmpty(hid))
                return CodeStatus.error_201.GetStatus($"{nameof(hid)}必传");
            T_User user = T_UserDal.GetAsNoTracking(a => a.user_id == userid && a.hospital_id == hid).FirstOrDefault();
            if (user == null)
                return CodeStatus.error_202.GetStatus("无用户");

            ResultInfo res = GetListReport(user.user_idcard,user.user_phone,user.hospital_id);

            // 本人查询
            bool b = InsQueryReportRecord(user.user_id, user.user_idcard, user.user_name, user.user_phone, user.hospital_id, SearchReportTypeEnum.oneself.GetEnumDesc());
            if (!b)
                return CodeStatus.error_301.GetStatus("查询记录插入失败");

            return res;
        }

        /// <summary>
        /// 获取报告列表
        /// </summary>
        /// <param name="idcard"></param>
        /// <param name="phone"></param>
        /// <param name="hid"></param>
        /// <returns></returns>
        public ResultInfo GetListReport(string idcard, string phone, string hid)
        {
            ResultInfo res = CodeStatus.success.GetStatus();
            List<TJ_TiJianB> list = new List<TJ_TiJianB>();
            if (!string.IsNullOrWhiteSpace(idcard))
            {
                List<TJ_TiJianB> listIdCard = TJ_TiJianBDal.GetAsNoTracking(a => a.身份证号 == idcard && a.单位ID == hid).OrderByDescending(u => u.体检号).ToList();
                list.AddRange(listIdCard);
            }

            if (!string.IsNullOrWhiteSpace(phone))
            {
                List<TJ_TiJianB> listPhone = TJ_TiJianBDal.GetAsNoTracking(a => a.联系电话 == phone && a.单位ID == hid).OrderByDescending(u => u.体检号).ToList();
                list.AddRange(listPhone);
            }

            // 去重
            List<TJ_TiJianB> listTJ = list.Distinct(a => a.体检号).ToList();

            List<ReportModel> listReportModel = null;
            if (listTJ != null && listTJ.Count > 0)
            {
                listReportModel = new List<ReportModel>();

                foreach (TJ_TiJianB tjb in listTJ)
                {
                    ReportModel reportModel = GetReportModel(tjb, hid);
                    listReportModel.Add(reportModel);
                }
            }

            res.data = new { list = listReportModel };
            return res;
        }

        /// <summary>
        /// 获取报告详情
        /// </summary>
        /// <param name="ticket"></param>
        /// <returns></returns>
        public ResultInfo GetReportDetail(string ticket)
        {
            if (string.IsNullOrEmpty(ticket))
                return CodeStatus.error_201.GetStatus($"{nameof(ticket)}不能为空");
            ReportTicket reportTiecket = null;
            try
            {
                string json = DesUtils.Decrypt(ticket);
                reportTiecket = JsonXmlUtils.DeserializeObject<ReportTicket>(json);
            }
            catch
            {
                return CodeStatus.error_210.GetStatus();
            }

            int seconds = (int)DateTime.Now.Subtract(reportTiecket.now).TotalSeconds;
            if (seconds > ConfigSource.timeout)
                return CodeStatus.error_211.GetStatus();

            TJ_TiJianB tjb = TJ_TiJianBDal.GetAsNoTracking(a => a.单位ID == reportTiecket.hid && a.体检号 == reportTiecket.tjh).FirstOrDefault();
            if (tjb == null)
                return CodeStatus.error_202.GetStatus("无体检信息");

            //  获取报告
            List<TJ_BAOGAO> listBaoGao = TJ_BAOGAODal.GetAsNoTracking(a => a.单位ID == reportTiecket.hid && a.体检号 == reportTiecket.tjh).OrderBy(a => a.科室顺序).ToList();
            List<TJ_BAOGAO> listDisTinctBaoGao =  listBaoGao.Distinct(a => a.流水号).ToList();
            // 获取所有的图像报告
            List<TJ_Images> listImg = TJ_ImagesDal.GetAsNoTracking(a => a.单位ID == reportTiecket.hid && a.体检号 == reportTiecket.tjh).ToList();
            List<TJ_Images> listDictinctImg = listImg.Distinct(a => a.项目编码).ToList();
            // 查询所有的配置信息
            List<S_Report_ItemConfig> listConfig = S_Report_ItemConfigDal.GetAsNoTracking(a => true).ToList();

            ReportDetailModel reportDetailModel = GetReportResult(tjb, listDisTinctBaoGao, listDictinctImg, listConfig);

            ResultInfo res = CodeStatus.success.GetStatus();
            res.data = reportDetailModel;
            return res;
        }

        public ResultInfo GetReportImage(string ticket)
        {
            if (string.IsNullOrEmpty(ticket))
                return CodeStatus.error_201.GetStatus($"{nameof(ticket)}必传");

            ReportImgTicket reportImgTicket = null;
            try
            {
                string json = DesUtils.Decrypt(ticket);
                reportImgTicket = JsonXmlUtils.DeserializeObject<ReportImgTicket>(json);
            }
            catch
            {
                return CodeStatus.error_210.GetStatus();
            }

            List<byte[]> listImg = TJ_ImagesDal.GetAsNoTracking(a => a.单位ID == reportImgTicket.hid && a.体检号 == reportImgTicket.tjh && a.项目编码 == reportImgTicket.xmbm).OrderBy(a => a.序号).Select(a => a.图像).ToList();
            List<object> listResult = new List<object>();

            foreach (byte[] info in listImg)
            {
                Image image = ImgUtils.GetImageByBytes(info);
                int width = image.Width;
                int height = image.Height;

                string str = Convert.ToBase64String(info);

                var obj = new { base64img = str, width = width, height = height };
                listResult.Add(obj);
            }

            ResultInfo res = CodeStatus.success.GetStatus();
            res.data = new { list = listResult };

            return res;
        }

        private bool InsQueryReportRecord(string userid,string idcard,string name,string phone,string hid,string searchType)
        {
            T_QueryReport_Record record = new T_QueryReport_Record();
            record.id = IDGeneratorUtils.NewWorkid();
            record.user_id = userid;
            record.search_type = searchType;
            record.query_idcard = idcard;
            record.query_name = name;
            record.query_phone = phone;
            record.hospital_id = hid;
            record.create_userid = userid;
            record.create_time = DateTime.Now;

            return T_QueryReport_RecordDal.Add(record);
        }

        private ReportDetailModel GetReportResult(TJ_TiJianB tjb, List<TJ_BAOGAO> listBaoGao, List<TJ_Images> listImg, List<S_Report_ItemConfig> listConfig)
        {
            string type_table = ItemConfigTypeEnum.table.GetEnumDesc();
            string type_list = ItemConfigTypeEnum.list.GetEnumDesc();

            ReportDetailModel reportDetailModel = new ReportDetailModel();
            reportDetailModel.summary = tjb.总结;
            reportDetailModel.propose = tjb.建议;
            reportDetailModel.check_doctor_name = tjb.总检医生;
            reportDetailModel.check_time = tjb.总检日期;
            reportDetailModel.examine_doctor_name = tjb.审核医生;
            reportDetailModel.examine_time = tjb.审核日期;
            reportDetailModel.zyb_propose = tjb.职业病建议;
            reportDetailModel.zyb_result = tjb.职业病结果;

            List<ReportDeptInfo> listReportDeptInfo = new List<ReportDeptInfo>();
            // 科室名称分组
            List<string> listDeptName = listBaoGao.GroupBy(a => a.科室名称).Select(a => a.Key).ToList();
            foreach (string deptName in listDeptName)
            {
                ReportDeptInfo reportDeptInfo = new ReportDeptInfo();
                reportDeptInfo.dept_name = deptName;
                // 配置的科室名称是否包含，没有就默认
                S_Report_ItemConfig itemDeptConfig = listConfig.Where(a => deptName.Contains(a.dept_name)).FirstOrDefault();
                if (itemDeptConfig == null)
                    reportDeptInfo.config_name = type_table;
                else
                    reportDeptInfo.config_name = itemDeptConfig.config_type;

                // 科室下面项目的操作
                List<TJ_BAOGAO> listDeptBaoGao = listBaoGao.Where(a => a.科室名称 == deptName).ToList();
                // 组合项目分组
                List<string> listCombItemName = listDeptBaoGao.GroupBy(a => a.组合项目名称).Select(a => a.Key).ToList();

                List<ReportCombItemInfo> listReportCombItemInfo = new List<ReportCombItemInfo>(); // 表格

                foreach (string combName in listCombItemName)
                {
                    ReportCombItemInfo reportCombItemInfo = new ReportCombItemInfo();

                    List<ReportItemInfo> listReportItemInfoTable = new List<ReportItemInfo>();
                    List<ReportItemInfo> listReportItemInfoList = new List<ReportItemInfo>();

                    // 组合项目下面的记录
                    List<TJ_BAOGAO> listCombItemBaoGao = listDeptBaoGao.Where(a => a.组合项目名称 == combName).ToList();
                    // 对项目进行筛选
                    foreach (TJ_BAOGAO bg in listCombItemBaoGao)
                    {
                        if (bg.结果 == "拒检")
                            continue;
                        ReportItemInfo reportItemInfo = null;
                        if (itemDeptConfig != null)
                        {
                            List<S_Report_ItemConfig> listItemConfig = listConfig.Where(a => a.fid == itemDeptConfig.id).ToList();
                            // 是否包含项目名称和类型是列表
                            S_Report_ItemConfig itemConfig = listItemConfig.Where(a => a.config_type == type_list && bg.项目名称.Contains(a.item_name)).FirstOrDefault();
                            // 列表就加到listReportCombItemInfoList这里
                            if (itemConfig != null)
                            {
                                reportItemInfo = GetReportItemInfo(bg, listImg, itemConfig.config_type); // type_list
                                listReportItemInfoList.Add(reportItemInfo);
                            }
                            else
                            {
                                reportItemInfo = GetReportItemInfo(bg, listImg, type_table);
                                listReportItemInfoTable.Add(reportItemInfo);
                            }
                        }
                        else
                        {
                            reportItemInfo = GetReportItemInfo(bg, listImg, type_table);
                            listReportItemInfoTable.Add(reportItemInfo);
                        }
                    }

                    reportCombItemInfo.comb_item_name = combName;
                    reportCombItemInfo.item_table = listReportItemInfoTable;
                    reportCombItemInfo.item_list = listReportItemInfoList;

                    listReportCombItemInfo.Add(reportCombItemInfo);

                }

                reportDeptInfo.comb_item = listReportCombItemInfo;
                listReportDeptInfo.Add(reportDeptInfo);
            }

            reportDetailModel.list = listReportDeptInfo;
            return reportDetailModel;
        }

        private ReportItemInfo GetReportItemInfo(TJ_BAOGAO bg, List<TJ_Images> listImg, string configName)
        {
            ReportItemInfo reportItemInfo = new ReportItemInfo();
            reportItemInfo.item_name = bg.项目名称;
            reportItemInfo.unit = bg.单位;
            reportItemInfo.ref_value = bg.参考值;
            reportItemInfo.result = bg.结果;
            reportItemInfo.check_doctor_name = bg.检查医生;
            reportItemInfo.check_time = bg.检查时间;
            reportItemInfo.dept_summary = bg.科室小结;
            reportItemInfo.diag_summary = bg.诊断小结;
            reportItemInfo.tips = bg.提示;
            reportItemInfo.img_count = listImg.Where(a => a.项目编码 == bg.项目编码).Count();

            if (reportItemInfo.img_count > 0)
            {
                ReportImgTicket reportImgTicket = new ReportImgTicket();
                reportImgTicket.hid = bg.单位ID;
                reportImgTicket.tjh = bg.体检号;
                reportImgTicket.xmbm = bg.项目编码;
                reportImgTicket.rand_num = Guid.NewGuid().ToString();
                reportItemInfo.img_ticket = JsonXmlUtils.SerializeObject(reportImgTicket);
            }
            reportItemInfo.config_name = configName;
            return reportItemInfo;
        }

        private ReportModel GetReportModel(TJ_TiJianB tjb, string hid)
        {
            ReportModel reportModel = new ReportModel();
            reportModel.tjlsh = tjb.体检流水号;
            reportModel.tjh = tjb.体检号;
            reportModel.idcard = StringUtils.ReplaceWithSpecialChar(tjb.身份证号);
            reportModel.phone = StringUtils.ReplaceWithSpecialChar(tjb.联系电话);
            reportModel.name = tjb.姓名;
            reportModel.sex = tjb.性别;
            reportModel.age = tjb.年龄 == null ? "" : tjb.年龄.ToString();
            reportModel.tjrq = tjb.体检日期;
            reportModel.package_name = tjb.套餐名称;
            reportModel.company_name = tjb.单位名称;
            reportModel.dept_name = tjb.部门;
            reportModel.summary = tjb.总结;
            reportModel.propose = tjb.建议;
            reportModel.check_doctor_name = tjb.总检医生;
            reportModel.check_time = tjb.总检日期;
            reportModel.examine_doctor_name = tjb.审核医生;
            reportModel.examine_time = tjb.审核日期;
            reportModel.zyb_propose = tjb.职业病建议;
            reportModel.zyb_result = tjb.职业病结果;
            reportModel.category_name = tjb.体检类别;
            reportModel.is_pdf = false;
            string url = TJ_PDF_BGDal.GetPDF(hid, reportModel.tjh);
            if (!string.IsNullOrEmpty(url))
            {
                reportModel.is_pdf = true;
                reportModel.pdf_url = ConfigSource.api_url + url;
            }

            ReportTicket reportTicket = GetReportTicket(reportModel.tjh, hid);
            string ticketStr = JsonXmlUtils.SerializeObject(reportTicket);
            reportModel.report_ticket = DesUtils.Encrypt(ticketStr);
            return reportModel;
        }

        private ReportTicket GetReportTicket(string tjh, string hid)
        {
            ReportTicket reportTicket = new ReportTicket();
            reportTicket.tjh = tjh;
            reportTicket.now = DateTime.Now;
            reportTicket.randnum = Guid.NewGuid().ToString();
            reportTicket.hid = hid;
            return reportTicket;
        }
    }
}
